﻿using System.Collections.Generic;
using Newtonsoft.Json;

namespace SmartMotion.Core
{
    /// <summary>
    /// 运动控制器基类，它的子类可能有运动控制卡，外置运动控制器，4轴机械手，6轴机械手，PLC，淘宝杂牌运动控制器
    /// 共同的属性和行为有，初始化，打开关闭，轴列表，IO列表，多轴运动，插补，连续插补，位置比较等
    /// </summary>
    public abstract class MotionControlBase : BindableBase, IIOCtrl
    {
        protected MotionControlBase(ushort cardID)
        {
            CardID = cardID;
            Axises = new List<AxisBase>();
            AxisesID = new List<string>();
            DI = new List<IOIn>();
            DO = new List<IOOut>();
            DIID = new List<string>();
            DOID = new List<string>();
        }

        public ushort CardID { get; }

        [JsonIgnore]
        public List<AxisBase> Axises { get; set; }

        /// <summary>
        /// 板卡创建轴后，下次反序列化由ID找到轴
        /// </summary>
        public List<string> AxisesID { get; set; }

        #region 常见功能

        //初始化，打开
        //释放卡，关闭
        //复位
        //获取轴
        //获取IO
        //设备号，卡号
        //是否连接控制器
        //停止所有轴
        //-----------多轴相关的属性和行为
        //获取，设置插补速度
        //多轴插补,直线插补，圆弧插补，螺旋插补
        //----------连续插补
        //清空连续插补队列
        //增加直线插补
        //增加圆弧插补
        //增加延时
        //等待IO
        //输出
        //启动连续插补
        //暂停连续插补
        //停止连续插补
        //获取连续插补状态

        #endregion 常见功能

        #region 运动控制器

        //Step1
        /// <summary>
        /// 初始化,或打开
        /// </summary>
        /// <returns></returns>
        public abstract int Init();

        /// <summary>
        /// 关闭
        /// </summary>
        /// <returns></returns>
        public abstract int Close();

        //Step2

        //Step3
        /// <summary>
        /// 紧急停止所有轴
        /// </summary>
        /// <returns></returns>
        public abstract int EmgStop();

        //Step4

        public abstract int GetErrcode(out int errcode);

        public abstract int ClearErrcode();

        public abstract int Reset();

        public abstract List<AxisBase> CreateAxisses(int axisCount);

        #endregion 运动控制器

        #region 群组运动

        //Step7, 多轴运动，插补，连续插补

        public abstract int SetGroupSpeed(ushort group, double minVel, double maxVel, double acc, double dec, double stopVel);

        public abstract int SetGroupSpeed(ushort group, Speed speed);

        public abstract int SetGroupSpeed(ushort group, double rate);//推荐，速度比例

        public abstract int GetGroupSpeed(ushort group, out double minVel, out double maxVel, out double acc, out double dec, out double stopVel);

        public abstract int GetGroupSpeed(ushort group, out Speed speed);

        public abstract int GetGroupSpeed(ushort group, out double rate);//推荐，速度比例

        /// <summary>   
        /// 线性插补
        /// </summary>

        /// <param name="group">群组号，插补系，坐标系</param>
        /// <param name="axisNum">参与插补的轴数量</param>
        /// <param name="axisList">参与插补的轴数组</param>
        /// <param name="targetPos">目标位置数组</param>
        /// <param name="posiMode">运动模式，相对运动或绝对运动</param>
        /// <returns></returns>
        public abstract int LineMove(ushort group, ushort axisNum, ushort[] axisList, double[] targetPos, int posiMode);

        /// <summary>
        /// 检查多轴运动是否完成
        /// </summary>

        /// <param name="group">坐标系，群组，插补系</param>
        /// <returns></returns>
        public abstract int CheckDoneMultiAxis(ushort group);

        #endregion 群组运动

        #region IoCtrl接口

        public abstract bool InitIoCtrl();

        public abstract bool CloseIoCtrl();

        public List<IOIn> CreateInputIO(int inputCount)
        {

            for (int i = 0; i < inputCount; i++)
            {
                var input = new IOIn()
                {
                    IOIndex = i,

                };
                DI.Add(input);
            }

            return DI;
        }

        public List<IOOut> CreateOutputIO(int outputCount)
        {
            for (int i = 0; i < outputCount; i++)
            {
                var output = new IOOut()
                {
                    IOIndex = i,
                };
                DO.Add(output);
            }

            return DO;
        }


        public abstract int ReadInBit(ushort bitNo);

        public abstract int ReadOutBit(ushort bitNo);

        public abstract int ReadInPort(ushort portNo);

        public abstract int ReadOutPort(ushort portNo);

        public abstract int WriteOutbit(ushort bitNo, ushort onOff);

        public abstract int WriteOutPort(ushort portNo, ushort portValue);

        public List<IOIn> DI { get; }

        public List<IOOut> DO { get; }

        public List<string> DIID { get; }

        public List<string> DOID { get; }

        #endregion IoCtrl接口
    }
}